package vn.lumi.smarthome.network;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

import com.google.analytics.tracking.android.Log;

import android.R.integer;
import android.content.Context;
import android.view.animation.CycleInterpolator;

import vn.lumi.smarthome.io.model.Device;
import vn.lumi.smarthome.io.model.DeviceState;
import vn.lumi.smarthome.io.model.Floor;
import vn.lumi.smarthome.io.model.Room;
import vn.lumi.smarthome.io.model.Scene;
import vn.lumi.smarthome.io.model.Schedule;
import vn.lumi.smarthome.io.model.Time;
import vn.lumi.smarthome.provider.SmartHomeProvider;

public class Config extends HCMsg {

	// constants

	// Attributes
	private ArrayList<Floor> floors = new ArrayList<Floor>();

	public Config() {
		super(NetMessage.CMD_HC_CONFIG, 0);
	}

	@Override
	public void parseMessage(byte[] input, int length) {
		if (this.isCorrectFormat(input, length) == true) {
			int NumberOfRoom = Byte2Unsigned(input[1]);
			System.out.println("number of room = " + NumberOfRoom);
			int currentPos = 2;

			// Rooms
			for (int i = 0; i < NumberOfRoom; i++) {
				Room room = new Room();
				int roomID = Byte2Unsigned(input[currentPos]);
				room.setId(roomID);
				currentPos++;
				byte[] name = new byte[30];
				for (int j = 0; j < 30; j++) {
					name[j] = input[currentPos];
					currentPos++;
				}
				try {
					room.setName(new String(name, "UTF-16BE"));
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				room.setFloor_id(Byte2Unsigned(input[currentPos]));
				currentPos++;
				System.out.println("Room_id = " + room.getId() + " Name = "
						+ room.getName() + " floor id=" + room.getFloor_id());
				// add new floor if needed
				if (floors.size() == 0) {
					Floor floor = new Floor();
					floor.setId(room.getFloor_id());
					floor.setName(SmartHomeProvider.getFloorName(floor.getId()));
					floor.addRoom(room);
					floors.add(floor);
				} else {
					boolean isNewFloor = true;
					for (int i1 = 0; i1 < floors.size(); i1++) {
						if (floors.get(i1).getId() == room.getFloor_id()) {
							isNewFloor = false;
							floors.get(i1).addRoom(room);
							break;
						}
					}
					if (isNewFloor == true) {
						Floor floor = new Floor();
						floor.setId(room.getFloor_id());
						floor.setName(SmartHomeProvider.getFloorName(floor
								.getId()));
						floor.addRoom(room);
						floors.add(floor);
					}
				}
			}
			ArrayList<Device> devices = new ArrayList<Device>();
			// Devices
			for (int numType = 1; numType <= NetMessage.numOfTMDE; numType++) {

				int NumOfDevices = Byte2Unsigned(input[currentPos]);
				currentPos += 1;
				for (int i = 0; i < NumOfDevices; i++) {
					Device device = new Device();
					// android.util.Log.e("currentPos", "" + currentPos
					// + "size input[] =" + input.length);
					// android.util.Log.e("ban tin", "NumOfDevices" +
					// NumOfDevices);
					device.setId(Byte2Unsigned(input[currentPos]));
					currentPos++;
					device.setRoom_id(Byte2Unsigned(input[currentPos]));
					currentPos++;
					byte[] dev_name = new byte[20];
					for (int k = 0; k < 20; k++) {
						dev_name[k] = (input[currentPos]);
						currentPos++;
					}
					try {
						device.setName(new String(dev_name, "UTF-16BE"));
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
					device.setType_id(Byte2Unsigned(input[currentPos]));
					currentPos++;
					int stateLength = SmartHomeProvider
							.getStateLengthByType(device.getType_id());

					// test
					if (stateLength < 1) {
						currentPos++;
						continue;
					}

					int[] state = new int[stateLength];
					for (int k = 0; k < stateLength; k++) {
						state[k] = Byte2Unsigned(input[currentPos]);
						currentPos++;
					}
					device.setDeviceState(SmartHomeProvider
							.getDeviceStateByType(device.getType_id(), state));

					// Author:hieu Schedule
					int NumofSchedule = Byte2Unsigned(input[currentPos]);
					currentPos++;
					if (NumofSchedule != 0) {

						for (int x = 1; x <= NumofSchedule; x++) {
							int schedule_id = Byte2Unsigned(input[currentPos]);
							currentPos++;
							int schedule_state = Byte2Unsigned(input[currentPos]);
							currentPos++;
							// int repeatAndDate =
							// Byte2Unsigned(input[currentPos]);
							// Lay cac thong so ve lich
							byte repeatAndDate = input[currentPos];
							currentPos++;
							boolean isRepeat = false;
							boolean isMonday = false;
							boolean isTuesday = false;
							boolean isWnesday = false;
							boolean isThusday = false;
							boolean isFriday = false;
							boolean isSatday = false;
							boolean isSunday = false;
							for (int n = 0; n <= 7; n++) {
								switch (n) {
								case 0:
									if (((repeatAndDate << n) & 0x80) >> 7 == 1) {
										isRepeat = true;
									} else
										isRepeat = false;
									break;
								case 1:
									if (((repeatAndDate << n) & 0x80) >> 7 == 1) {
										isMonday = true;
									} else
										isMonday = false;
									break;

								case 2:
									if (((repeatAndDate << n) & 0x80) >> 7 == 1) {
										isTuesday = true;
									} else
										isTuesday = false;
									break;
								case 3:
									if (((repeatAndDate << n) & 0x80) >> 7 == 1) {
										isWnesday = true;
									} else
										isWnesday = false;
									break;
								case 4:
									if (((repeatAndDate << n) & 0x80) >> 7 == 1) {
										isThusday = true;
									} else
										isThusday = false;
									break;
								case 5:
									if (((repeatAndDate << n) & 0x80) >> 7 == 1) {
										isFriday = true;
									} else
										isFriday = false;
									break;
								case 6:
									if (((repeatAndDate << n) & 0x80) >> 7 == 1) {
										isSatday = true;
									} else
										isSatday = false;
									break;
								case 7:
									if (((repeatAndDate << n) & 0x80) >> 7 == 1) {
										isSunday = true;
									} else
										isSunday = false;
									break;
								default:
									break;
								}
							}

							//

							int hour = Byte2Unsigned(input[currentPos]);
							currentPos++;
							int minute = Byte2Unsigned(input[currentPos]);
							currentPos++;
//							int Duration = Byte2Unsigned(input[currentPos]);
							int hour_end = Byte2Unsigned(input[currentPos]);
							currentPos++;
							int minute_end = Byte2Unsigned(input[currentPos]);
							currentPos++;
							int[] stateDeviceofSchedule = new int[stateLength];
							for (int k = 0; k < stateLength; k++) {
								stateDeviceofSchedule[k] = Byte2Unsigned(input[currentPos]);
								currentPos++;
							}

							// Luu y : ma state_id se de luc update vao co so du
							// lieu
							// roi set lai state_id cho schedule
							Schedule schedule = new Schedule(schedule_id,
									device.getId(), schedule_state, isRepeat,
									isMonday, isTuesday, isWnesday, isThusday,
									isFriday, isSatday, isSunday, hour, minute,
									hour_end,minute_end, 0);
							schedule.setDeviceState(SmartHomeProvider
									.getDeviceStateByType(device.getType_id(),
											stateDeviceofSchedule));
							// check if HC send an existing schedule in list
							boolean isRepeatedSchedule = false;
							for (int k = 0; k < device.getCountSchedule(); k++) {
								if (device.getSchedule(k).getId() == schedule
										.getId()) {
									isRepeatedSchedule = true;
									// android.util.Log.e("ban tin",
									// "ScheduleisRepeat");
									break;
								}
							}
							if (isRepeatedSchedule == true)
								continue;
							// add schedule vao device
							device.setSchedule(schedule);
						}
					}
					// end Schedule
					// android.util.Log.e("state_length", "state_length: " +
					// stateLength);
					// check if HC send an existing device in list
					boolean isRepeatedDevice = false;
					for (int k = 0; k < devices.size(); k++) {
						if (devices.get(k).getId() == device.getId()) {
							isRepeatedDevice = true;
							// android.util.Log.e("ban tin", "DeviceisRepeat");
							break;
						}
					}
					if (isRepeatedDevice == true)
						continue;
					devices.add(device);
					System.out.println("Device_id = " + device.getId()
							+ " Name = " + device.getName() + " type = "
							+ device.getType_id() + " room_id="
							+ device.getRoom_id() + " value="
							+ device.getDeviceState().getValue() + " rgb="
							+ device.getDeviceState().getRGB()
							+ " blind_state="
							+ device.getDeviceState().getBlind_state());
				}
			}

			// Scenes
			ArrayList<Scene> scenes = new ArrayList<Scene>();
			for (int numType = 1; numType <= NetMessage.numOfTMSE; numType++) {
				int NumOfScenes = Byte2Unsigned(input[currentPos]);
				currentPos++;
				for (int i = 0; i < NumOfScenes; i++) {
					int scene_id = Byte2Unsigned(input[currentPos]);
					currentPos++;
					int scene_state = Byte2Unsigned(input[currentPos]);
					currentPos++;
					int room_id = Byte2Unsigned(input[currentPos]);
					currentPos++;
					// scene name

					byte[] scene_name_byte = new byte[30];
					String scene_name = "";
					for (int k = 0; k < 30; k++) {
						scene_name_byte[k] = (input[currentPos]);
						currentPos++;
					}
					try {
						scene_name = new String(scene_name_byte, "UTF-16BE");
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
					int scene_mode = Byte2Unsigned(input[currentPos]);
					currentPos++;
					Time time = new Time(Byte2Unsigned(input[currentPos]),
							Byte2Unsigned(input[currentPos + 1]));
					currentPos += 2;
					int NumOfNormalDevices = Byte2Unsigned(input[currentPos]);
					currentPos++;
					int NumOfRGBs = Byte2Unsigned(input[currentPos]);
					currentPos++;
					int NumOfAllDevices = NumOfNormalDevices + NumOfRGBs;
					ArrayList<Integer> devices_id = new ArrayList<Integer>();
					ArrayList<DeviceState> devices_state = new ArrayList<DeviceState>();
					for (int j = 0; j < NumOfAllDevices; j++) {
						int device_id = Byte2Unsigned(input[currentPos]);
						currentPos++;
						// find device type
						int device_type = -1;
						for (Device dev : devices) {
							if (dev.getId() == device_id) {
								device_type = dev.getType_id();
								break;
							}
						}
						if (device_type == -1)
							break;
						int stateLength = SmartHomeProvider
								.getStateLengthByType(device_type);
						if (stateLength == -1)
							break;
						int[] state = new int[stateLength];
						for (int k = 0; k < stateLength; k++) {
							state[k] = Byte2Unsigned(input[currentPos]);
							currentPos++;
						}
						devices_id.add(device_id);
						devices_state.add(SmartHomeProvider
								.getDeviceStateByType(device_type, state));
					}
					Scene scene = new Scene(scene_id, room_id, scene_name,
							scene_state, devices_id, devices_state, scene_mode,
							time);
					scenes.add(scene);
					System.out.println("Scene: id=" + scene_id + " room_id="
							+ room_id + " name=" + scene_name + " state="
							+ scene_state + " mode=" + scene_mode + " hour="
							+ time.getHour() + " minute=" + time.getMinute());
					for (int j = 0; j < devices_id.size(); j++) {
						// System.out
						// .print("device_id="
						// + scene.getDevicesId().get(j)
						// + " value="
						// + scene.getDevicesState().get(j).getValue()
						// + " blind_state="
						// + scene.getDevicesState().get(j)
						// .getBlind_state() + " RGB="
						// + scene.getDevicesState().get(j).getRGB());
					}
					// System.out.print("===================================");
				}
			}

			// add devices and scenes to room
			for (int t = 0; t < floors.size(); t++) {
				for (int w = 0; w < floors.get(t).getRooms().size(); w++) {
					for (int z = 0; z < devices.size(); z++) {
						if (floors.get(t).getRooms().get(w).getId() == devices
								.get(z).getRoom_id()) {
							// add device to room
							floors.get(t).getRooms().get(w)
									.addDevice(devices.get(z));
						}
					}
					for (int q = 0; q < scenes.size(); q++) {
						if (floors.get(t).getRooms().get(w).getId() == scenes
								.get(q).getRoom_id())
							// add scene to room
							floors.get(t).getRooms().get(w)
									.addScene(scenes.get(q));
					}
				}
			}
		}
	}

	public ArrayList<Floor> getFloors() {
		return floors;
	}

	@Override
	public void doWhenReceived(Context context) {
		// TODO Auto-generated method stub

	}
}
